$TITLE ('INTERRUPT ATTACH AND DETACH FUNCTION CALLS')
$SYMBOLS
$NOXREF
$NOCOND
$NOMOD51
$NORB
$PAGELENGTH(80) PAGEWIDTH(110)
;************************************************************************
;*									*
;*    R T X - 5 1  :  INTERRUPT ATTACH/DETACH FUNCTION CALLS            *
;*							     		*
;*----------------------------------------------------------------------*
;*                                                                      *
;*    Filename     :   RTXATTA.A51                                      *
;*    Language     :   Keil A-51                                        *
;*    Dev. system  :   Keil uVision2                                    *
;*    Targetsystem :   Any system based upon 8051 up                    *
;*                                                                      *
;*    Purpose      :   Implements the os_attach_interrupt and           *
;*                     os_detach_interrupt function calls.              *
;*								     	*
;*----------------------------------------------------------------------*
;* Rev. |  Released   | Programmer    | Comments                        *
;*----------------------------------------------------------------------*
;* 0.1  |  28.05.1991 | Th. Fischler  | Module creation                 *
;* 4.24 |  15.04.1994 | E. Glatz      | Wrong instruction MOV @DPTR,A in*
;*      |             |               | 'os_detach_interrupt' eliminated*
;* 5.00 |  20.10.1994 |               | Release 5.00                    *
;* 7.00 |  13.11.2001 | T. Mueller    | Release 7.00                    *
;************************************************************************
;*    Copyright 1991 .. 2001 METTLER  &  FUCHS  AG,  CH-8953 Dietikon   *
;************************************************************************


$INCLUDE (RTXDEBUG.INC)
$INCLUDE (RTXIMASK.INC)


;*----------------------------------------------------------------------*
;*	I M P O R T S
;*----------------------------------------------------------------------*

$INCLUDE (RTXCONST.INC)
$INCLUDE (RTXEXTRN.INC)

;	FROM RTXDISP
EXTRN   CODE    (?RTX_REDISPATCH)


;*----------------------------------------------------------------------*
;*	E X P O R T S
;*----------------------------------------------------------------------*

PUBLIC  _os_attach_interrupt
PUBLIC  _os_detach_interrupt


;*----------------------------------------------------------------------*
;*	P R O C E D U R E S
;*----------------------------------------------------------------------*

;*----------------------------------------------------------------------*
;*      O S _ A T T A C H _ I N T E R R U P T
;*----------------------------------------------------------------------*
;*      System call for attaching an interrupt to the running task.
;*----------------------------------------------------------------------*
;*      Input:  - R7 : interrupt number (0..31)
;*      -----
;*
;*      Output: - R7 : Function result (OK, NOT_OK)
;*      ------
;*
;*----------------------------------------------------------------------*

?RTX?_os_attach_interrupt?RTXATTA   SEGMENT CODE
                                       RSEG ?RTX?_os_attach_interrupt?RTXATTA

_os_attach_interrupt:
               DBG_SYS_ENTRY
               RTX_EXCLUDE_INT
               SETB  ?RTX_SUPERVISOR_MODE       ; Supervisor_mode := on
               RTX_ALLOW_DRV_INT

               ; Check the input parameter
               MOV   A, R7
               SETB  C
               SUBB  A, #?RTX_MAX_INT_NBR
               JC    PARA_OK1
               ; Input parameter is not ok
               MOV   R7, #NOT_OK
               JMP   END_ATTACH

PARA_OK1:      ; Check if the interrupt is used by an ISR
               MOV   DPTR, #?RTX_ISRDESCR
               MOV   A, R7
               MOVC  A, @A+DPTR
               JZ    NOT_ISR
               ; Interrupt is used by an ISR
               MOV   R7, #NOT_OK
               JMP   END_ATTACH

NOT_ISR:       ; Check if the processor supports this interrupt
               MOV   DPTR, #?RTX_INT_TO_BIT_TABLE_BASE
               MOV   A, R7
               MOV   B, #3                      ; 3 Bytes/INT in the table
               MUL   AB
               MOV   R0, A                      ; Save the ACC
               ; Load the Interrupt-masks to reg. R1/R2/R3
               MOVC  A, @A+DPTR
               ANL   A, #07FH                   ; To be sure EA-Bit not set
               MOV   R1, A
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               MOV   R2, A
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               MOV   R3, A
               ; Check the masks
               CLR   A
               ORL   A, R1
               ORL   A, R2
               ORL   A, R3
               JNZ   PROC_OK
               ; processor does nor support this interrupt
               MOV   R7, #NOT_OK
               JMP   END_ATTACH

PROC_OK:       RTX_EXCLUDE_INT
               ; Check if the interrupt is unused
               MOV   DPH, #HIGH(?RTX_INT_TID_TABLE_BASE)
               MOV   A, #LOW(?RTX_INT_TID_TABLE_BASE)
               ADD   A, R7
               MOV   DPL, A
               MOVX  A, @DPTR
               CJNE  A, #NIL_TID, INT_USED
               JMP   INT_UNUSED
INT_USED:      MOV   R7, #NOT_OK
               JMP   END_ATTACH

INT_UNUSED:    ; All OK, update the system vars
               MOV   A, ?RTX_RUNNING_TID
               MOVX  @DPTR, A                   ; int_tid[int_no]=?RTX_RUNNING_TID
               MOV   DPH, #HIGH(?RTX_STATE_TABLE)
               ANL   A, #01FH
               RL    A
               RL    A                          ; task_no * 4
               ADD   A, #LOW(?RTX_STATE_TABLE)
               MOV   DPL, A
               ; DPTR -> state_table[task_no]
               ; now update the interrupt-masks
               INC   DPTR
               MOVX  A, @DPTR
               ORL   A, R1
               MOVX  @DPTR, A
               INC   DPTR
               MOVX  A, @DPTR
               ORL   A, R2
               MOVX  @DPTR, A
               INC   DPTR
               MOVX  A, @DPTR
               ORL   A, R3
               MOVX  @DPTR, A
               MOV   R7, #OK

END_ATTACH:    RTX_EXCLUDE_INT
               JB    ?RTX_REQ_REDISPATCH, RED   ; Redispatch requested ?
					        ; No:
               CLR   ?RTX_SUPERVISOR_MODE       ; supervisor_mode := OFF
               DBG_SYS_EXIT
               RTX_ALLOW_INT
               RET

RED:           CLR   ?RTX_FULL_CONTEXT
               JMP   ?RTX_REDISPATCH



;*----------------------------------------------------------------------*
;*      O S _ D E T A C H _ I N T E R R U P T
;*----------------------------------------------------------------------*
;*      System call for detaching an interrupt from the running task.
;*----------------------------------------------------------------------*
;*      Input:  - R7 : interrupt number (0..31)
;*      -----
;*
;*      Output: - R7 : Function result (OK, NOT_OK)
;*      ------
;*
;*----------------------------------------------------------------------*

?RTX?_os_detach_interrupt?RTXATTA   SEGMENT CODE
                                       RSEG ?RTX?_os_detach_interrupt?RTXATTA

_os_detach_interrupt:
               DBG_SYS_ENTRY
               RTX_EXCLUDE_INT
               SETB  ?RTX_SUPERVISOR_MODE       ; Supervisor_mode := on

               ; Check the input parameter
               MOV   A, R7
               SETB  C
               SUBB  A, #?RTX_MAX_INT_NBR
               JC    PARA_OK2
               ; Input parameter is not ok
               MOV   R7, #NOT_OK
               JMP   END_DETACH

PARA_OK2:      ; Check if the interrupt is used by the running task
               MOV   DPH, #HIGH(?RTX_INT_TID_TABLE_BASE)
               MOV   A, #LOW(?RTX_INT_TID_TABLE_BASE)
               ADD   A, R7
               MOV   DPL, A
               MOVX  A, @DPTR
               CJNE  A, ?RTX_RUNNING_TID, INT_NOT_ATTACHED
               JMP   INT_ATTACHED
INT_NOT_ATTACHED:
               MOV   R7, #NOT_OK
               JMP   END_DETACH

INT_ATTACHED:  ; All OK, update system vars
               MOV   A, #NIL_TID
               MOVX  @DPTR, A                   ; int_tid[tid_no]=NIL_TID

               ; update the interrupt masks
               MOV   DPTR, #?RTX_INT_TO_BIT_TABLE_BASE
               MOV   A, R7
               MOV   B, #3                      ; 3 Bytes/INT in the table
               MUL   AB
               MOV   R0, A                      ; Save the ACC
               ; Load the inverted Interrupt-masks to reg. R1/R2/R3
               MOVC  A, @A+DPTR
               ANL   A, #07FH                   ; To be sure EA-Bit not set
               CPL   A
               MOV   R1, A
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               CPL   A
               MOV   R2, A
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               CPL   A
               MOV   R3, A

               MOV   A, ?RTX_RUNNING_TID
; ** X 4.24    MOVX  @DPTR, A                   ; int_tid[int_no]=?RTX_RUNNING_TID
               MOV   DPH, #HIGH(?RTX_STATE_TABLE)
               ANL   A, #01FH
               RL    A
               RL    A                          ; task_no * 4
               ADD   A, #LOW(?RTX_STATE_TABLE)
               MOV   DPL, A
               ; DPTR -> state_table[task_no]
               ; now update the interrupt-masks
               INC   DPTR
               MOVX  A, @DPTR
               ANL   A, R1
               MOVX  @DPTR, A
               INC   DPTR
               MOVX  A, @DPTR
               ANL   A, R2
               MOVX  @DPTR, A
               INC   DPTR
               MOVX  A, @DPTR
               ANL   A, R3
               MOVX  @DPTR, A
               MOV   R7, #OK

END_DETACH:    CLR   ?RTX_SUPERVISOR_MODE       ; supervisor_mode := OFF
               DBG_SYS_EXIT
               RTX_ALLOW_INT
               RET

;
;   END OF MODULE
;
	END
